[topgen] Restructure how we elaborate blocks into IP instances
There's no significant functional change, but this code should be a
bit simpler to understand and work with.
Because we now iterate over the instances in a different order (by
instance, rather than by block), the auto-generated random constants
are generated in a different order, so they change in the checked-in
top_earlgrey_rnd_cnst_pkg.sv.
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 200c52c..134b964 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -2417,7 +2417,7 @@
randcount: 64
randtype: data
name_top: RndCnstLcCtrlLcKeymgrDivInvalid
- default: 0xf4c3471c5def7861
+ default: 0x4440722325a93144
randwidth: 64
}
{
@@ -2427,7 +2427,7 @@
randcount: 64
randtype: data
name_top: RndCnstLcCtrlLcKeymgrDivTestDevRma
- default: 0x83d0550b80e84eb1
+ default: 0xfdb92558e2d9c5d2
randwidth: 64
}
{
@@ -2437,7 +2437,7 @@
randcount: 64
randtype: data
name_top: RndCnstLcCtrlLcKeymgrDivProduction
- default: 0x2d73930d4cac3785
+ default: 0xd1c09f5c02b2c8d1
randwidth: 64
}
]
@@ -2888,7 +2888,7 @@
randcount: 32
randtype: data
name_top: RndCnstAlertHandlerLfsrSeed
- default: 0x5def7861
+ default: 0x2bccd612
randwidth: 32
}
{
@@ -2898,7 +2898,7 @@
randcount: 32
randtype: perm
name_top: RndCnstAlertHandlerLfsrPerm
- default: 0x5f00c4cafd73fc4ac479a61068375f38956d84b3
+ default: 0xb265e7161a57cd840e2d9b32b38a840dc1c7f6bb
randwidth: 160
}
]
@@ -4122,7 +4122,7 @@
randcount: 128
randtype: data
name_top: RndCnstSramCtrlRetAonSramKey
- default: 0x83d0550b80e84eb1f4c3471c5def7861
+ default: 0x9fbb73a9bf8c393c12965c7de10023ec
randwidth: 128
}
{
@@ -4132,7 +4132,7 @@
randcount: 64
randtype: data
name_top: RndCnstSramCtrlRetAonSramNonce
- default: 0x2d73930d4cac3785
+ default: 0x60c06703b494b3ff
randwidth: 64
}
{
@@ -4329,7 +4329,7 @@
randcount: 128
randtype: data
name_top: RndCnstFlashCtrlAddrKey
- default: 0x83d0550b80e84eb1f4c3471c5def7861
+ default: 0x738f30d9006289a1d7d9d0ce1dd7d7c
randwidth: 128
}
{
@@ -4339,7 +4339,7 @@
randcount: 128
randtype: data
name_top: RndCnstFlashCtrlDataKey
- default: 0xfabd19450b238d4c2d73930d4cac3785
+ default: 0xfe8f673fba39bb679d58aa91aeb2691c
randwidth: 128
}
{
@@ -4349,7 +4349,7 @@
randcount: 32
randtype: data
name_top: RndCnstFlashCtrlLfsrSeed
- default: 0xd89f9dfc
+ default: 0xae24af11
randwidth: 32
}
{
@@ -4359,7 +4359,7 @@
randcount: 32
randtype: perm
name_top: RndCnstFlashCtrlLfsrPerm
- default: 0x26ff203d990d87c5e8a98bafec7506855aa99c54
+ default: 0x25da5869dc96fe354f1da55e9123cb082c63b331
randwidth: 160
}
]
@@ -4746,7 +4746,7 @@
randcount: 64
randtype: data
name_top: RndCnstAesClearingLfsrSeed
- default: 0xf4c3471c5def7861
+ default: 0x4b16446726a27b8f
randwidth: 64
}
{
@@ -4756,7 +4756,7 @@
randcount: 64
randtype: perm
name_top: RndCnstAesClearingLfsrPerm
- default: 0x26ac29e186c1f4dc6f959d6ed08dc044a0f3f1519e8dca131275df1e48bbf964ac772e613d0320adaebf38552dd822e6
+ default: 0x725022afed8c3f0c64f132a9fc5d1745d64ec881fded0e5fe8d9f8dee8215810deb1848952d123d552f36aa086a2f99b
randwidth: 384
}
{
@@ -4766,7 +4766,7 @@
randcount: 160
randtype: data
name_top: RndCnstAesMaskingLfsrSeed
- default: 0x19e5a91389b9fe0d3b818e46ce7d846469a3b8e3
+ default: 0xa77b61acd1356dc20cd7dd118e18edeb46b20763
randwidth: 160
}
{
@@ -4776,7 +4776,7 @@
randcount: 32
randtype: perm
name_top: RndCnstAesMskgChunkLfsrPerm
- default: 0x23f6ba7ea92aa0e8e3b900f826cee835bc1648fa
+ default: 0x311a5ecd60ff1f145c3265abec8d303a85ac3b74
randwidth: 160
}
]
@@ -5113,7 +5113,7 @@
randcount: 64
randtype: data
name_top: RndCnstKeymgrLfsrSeed
- default: 0xf4c3471c5def7861
+ default: 0xa26d06fed461e43e
randwidth: 64
}
{
@@ -5123,7 +5123,7 @@
randcount: 64
randtype: perm
name_top: RndCnstKeymgrLfsrPerm
- default: 0x26ac29e186c1f4dc6f959d6ed08dc044a0f3f1519e8dca131275df1e48bbf964ac772e613d0320adaebf38552dd822e6
+ default: 0xedf8195a833eb78d252d435c8b301b7b2bc36b6270c52908ae9b07eb9f615ee3f51444e641509876adfc28647f9e304e
randwidth: 384
}
{
@@ -5133,7 +5133,7 @@
randcount: 32
randtype: perm
name_top: RndCnstKeymgrRandPerm
- default: 0x86cb85d79423d404d9d717e683782c975a389f3a
+ default: 0x97cd1105dced6f9458f02a54bdf9ba9bc60a6184
randwidth: 160
}
{
@@ -5143,7 +5143,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrRevisionSeed
- default: 0xa917f063c414964e46ce0fe8ddb271067884ebcc4f232c841702ef7147e71b5c
+ default: 0x3c7a34558ccec99f160326db309c3ed8635b48d5dd14c50a053db7469bac5612
randwidth: 256
}
{
@@ -5153,7 +5153,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrCreatorIdentitySeed
- default: 0x84b1a5a63af5fa0aaf8c6a6b90f868a3f2590e4a1004f9cf620d8c56137d9287
+ default: 0x81a3637187c027b6aca8e4ffc89a3209a1642741192e3979e50f4b7302bf908c
randwidth: 256
}
{
@@ -5163,7 +5163,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrOwnerIntIdentitySeed
- default: 0x32949cc3635d1f47c8f05affc85f7d889ecd94b67eb674bbdf38d62d3622493
+ default: 0xdc165280c0509a5cbee310112a22e896651cdf06599bf6ffc17fff937de17023
randwidth: 256
}
{
@@ -5173,7 +5173,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrOwnerIdentitySeed
- default: 0xeec5e43d4b16446726a27b8f0b30ad5048bae844c87b69111a24d5e4442bcfb7
+ default: 0x36c5b3d0a873f50b0e273058caa5291bd06f88a44b8243ca1a45b215cc7256c
randwidth: 256
}
{
@@ -5183,7 +5183,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrSoftOutputSeed
- default: 0xab174a27f3e9a7da096f534d1a07eb42a37dbfb7be9bb6e69a7d3c5f369ae283
+ default: 0x44af7c286396d54f33ceb281d957bf9ed89305d88d8d71c2ca6258cc000da006
randwidth: 256
}
{
@@ -5193,7 +5193,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrHardOutputSeed
- default: 0x8fefbc18548dfcb2fd145395d417df2f55255e182efed724cf8370466a266421
+ default: 0xf085d06d98c25574d82449e1afa2201f312ea264f507a75d5b610152d8465246
randwidth: 256
}
{
@@ -5203,7 +5203,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrAesSeed
- default: 0xe390fce7275f3bce5145a3b8edb5f33fd64e96a5b7a45278102f4c28f70a5b08
+ default: 0xed2e99906a4afbd4dedb5cc59ef74e5ab14d5b983dd7598af12e48c599da1605
randwidth: 256
}
{
@@ -5213,7 +5213,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrHmacSeed
- default: 0x5f0e50f0c4cdf307b6cf85bd7669c05b0e5dbc9627c050e4936e54cc761467e
+ default: 0x198a2b804df44b9e44e1c905dcd81e3b8adcf2ea1eb87424e51caa14dbfbec75
randwidth: 256
}
{
@@ -5223,7 +5223,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrKmacSeed
- default: 0xc19175299f2746ea860d6c0dd7a42245f8e1d251d66cef31bce5f18f586239c4
+ default: 0x710581e83789a7b90140c94645887a4457e74cd0c4cca056411c89563d15b47b
randwidth: 256
}
{
@@ -5233,7 +5233,7 @@
randcount: 256
randtype: data
name_top: RndCnstKeymgrNoneSeed
- default: 0x350bb6b68440934dcb834f93689fe9e88ebd53404a1d7296f0cbdb8b82989aa7
+ default: 0xa2415e162f57f8aa2cce101e080c3a9db8ca70b49d1050c47fa9ce86f3443c8c
randwidth: 256
}
]
@@ -5908,7 +5908,7 @@
randcount: 128
randtype: data
name_top: RndCnstSramCtrlMainSramKey
- default: 0xb6d4b556d89f9dfcfabd19450b238d4c
+ default: 0xd0ec61b1bdcbc0e305b5e826ef06ff71
randwidth: 128
}
{
@@ -5918,7 +5918,7 @@
randcount: 64
randtype: data
name_top: RndCnstSramCtrlMainSramNonce
- default: 0x160733e752cad615
+ default: 0x3e4ef606d8cefa03
randwidth: 64
}
{
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey_rnd_cnst_pkg.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey_rnd_cnst_pkg.sv
index ee870d4..0199241 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey_rnd_cnst_pkg.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey_rnd_cnst_pkg.sv
@@ -31,17 +31,17 @@
////////////////////////////////////////////
// Compile-time random bits for lc state group diversification value
parameter lc_ctrl_pkg::lc_keymgr_div_t RndCnstLcCtrlLcKeymgrDivInvalid = {
- 64'hF4C3471C5DEF7861
+ 64'h4440722325A93144
};
// Compile-time random bits for lc state group diversification value
parameter lc_ctrl_pkg::lc_keymgr_div_t RndCnstLcCtrlLcKeymgrDivTestDevRma = {
- 64'h83D0550B80E84EB1
+ 64'hFDB92558E2D9C5D2
};
// Compile-time random bits for lc state group diversification value
parameter lc_ctrl_pkg::lc_keymgr_div_t RndCnstLcCtrlLcKeymgrDivProduction = {
- 64'h2D73930D4CAC3785
+ 64'hD1C09F5C02B2C8D1
};
////////////////////////////////////////////
@@ -49,12 +49,12 @@
////////////////////////////////////////////
// Compile-time random bits for initial LFSR seed
parameter alert_pkg::lfsr_seed_t RndCnstAlertHandlerLfsrSeed = {
- 32'h5DEF7861
+ 32'h2BCCD612
};
// Compile-time random permutation for LFSR output
parameter alert_pkg::lfsr_perm_t RndCnstAlertHandlerLfsrPerm = {
- 160'h5F00C4CAFD73FC4AC479A61068375F38956D84B3
+ 160'hB265E7161A57CD840E2D9B32B38A840DC1C7F6BB
};
////////////////////////////////////////////
@@ -62,12 +62,12 @@
////////////////////////////////////////////
// Compile-time random reset value for SRAM scrambling key.
parameter otp_ctrl_pkg::sram_key_t RndCnstSramCtrlRetAonSramKey = {
- 128'h83D0550B80E84EB1F4C3471C5DEF7861
+ 128'h9FBB73A9BF8C393C12965C7DE10023EC
};
// Compile-time random reset value for SRAM scrambling nonce.
parameter otp_ctrl_pkg::sram_nonce_t RndCnstSramCtrlRetAonSramNonce = {
- 64'h2D73930D4CAC3785
+ 64'h60C06703B494B3FF
};
////////////////////////////////////////////
@@ -75,22 +75,22 @@
////////////////////////////////////////////
// Compile-time random bits for default address key
parameter flash_ctrl_pkg::flash_key_t RndCnstFlashCtrlAddrKey = {
- 128'h83D0550B80E84EB1F4C3471C5DEF7861
+ 128'h738F30D9006289A1D7D9D0CE1DD7D7C
};
// Compile-time random bits for default data key
parameter flash_ctrl_pkg::flash_key_t RndCnstFlashCtrlDataKey = {
- 128'hFABD19450B238D4C2D73930D4CAC3785
+ 128'hFE8F673FBA39BB679D58AA91AEB2691C
};
// Compile-time random bits for initial LFSR seed
parameter flash_ctrl_pkg::lfsr_seed_t RndCnstFlashCtrlLfsrSeed = {
- 32'hD89F9DFC
+ 32'hAE24AF11
};
// Compile-time random permutation for LFSR output
parameter flash_ctrl_pkg::lfsr_perm_t RndCnstFlashCtrlLfsrPerm = {
- 160'h26FF203D990D87C5E8A98BAFEC7506855AA99C54
+ 160'h25DA5869DC96FE354F1DA55E9123CB082C63B331
};
////////////////////////////////////////////
@@ -98,23 +98,23 @@
////////////////////////////////////////////
// Default seed of the PRNG used for register clearing.
parameter aes_pkg::clearing_lfsr_seed_t RndCnstAesClearingLfsrSeed = {
- 64'hF4C3471C5DEF7861
+ 64'h4B16446726A27B8F
};
// Permutation applied to the LFSR of the PRNG used for clearing.
parameter aes_pkg::clearing_lfsr_perm_t RndCnstAesClearingLfsrPerm = {
- 128'h26AC29E186C1F4DC6F959D6ED08DC044,
- 256'hA0F3F1519E8DCA131275DF1E48BBF964AC772E613D0320ADAEBF38552DD822E6
+ 128'h725022AFED8C3F0C64F132A9FC5D1745,
+ 256'hD64EC881FDED0E5FE8D9F8DEE8215810DEB1848952D123D552F36AA086A2F99B
};
// Default seed of the PRNG used for masking.
parameter aes_pkg::masking_lfsr_seed_t RndCnstAesMaskingLfsrSeed = {
- 160'h19E5A91389B9FE0D3B818E46CE7D846469A3B8E3
+ 160'hA77B61ACD1356DC20CD7DD118E18EDEB46B20763
};
// Permutation applied to the LFSR chunks of the PRNG used for masking.
parameter aes_pkg::mskg_chunk_lfsr_perm_t RndCnstAesMskgChunkLfsrPerm = {
- 160'h23F6BA7EA92AA0E8E3B900F826CEE835BC1648FA
+ 160'h311A5ECD60FF1F145C3265ABEC8D303A85AC3B74
};
////////////////////////////////////////////
@@ -122,68 +122,68 @@
////////////////////////////////////////////
// Compile-time random bits for initial LFSR seed
parameter keymgr_pkg::lfsr_seed_t RndCnstKeymgrLfsrSeed = {
- 64'hF4C3471C5DEF7861
+ 64'hA26D06FED461E43E
};
// Compile-time random permutation for LFSR output
parameter keymgr_pkg::lfsr_perm_t RndCnstKeymgrLfsrPerm = {
- 128'h26AC29E186C1F4DC6F959D6ED08DC044,
- 256'hA0F3F1519E8DCA131275DF1E48BBF964AC772E613D0320ADAEBF38552DD822E6
+ 128'hEDF8195A833EB78D252D435C8B301B7B,
+ 256'h2BC36B6270C52908AE9B07EB9F615EE3F51444E641509876ADFC28647F9E304E
};
// Compile-time random permutation for entropy used in share overriding
parameter keymgr_pkg::rand_perm_t RndCnstKeymgrRandPerm = {
- 160'h86CB85D79423D404D9D717E683782C975A389F3A
+ 160'h97CD1105DCED6F9458F02A54BDF9BA9BC60A6184
};
// Compile-time random bits for revision seed
parameter keymgr_pkg::seed_t RndCnstKeymgrRevisionSeed = {
- 256'hA917F063C414964E46CE0FE8DDB271067884EBCC4F232C841702EF7147E71B5C
+ 256'h3C7A34558CCEC99F160326DB309C3ED8635B48D5DD14C50A053DB7469BAC5612
};
// Compile-time random bits for creator identity seed
parameter keymgr_pkg::seed_t RndCnstKeymgrCreatorIdentitySeed = {
- 256'h84B1A5A63AF5FA0AAF8C6A6B90F868A3F2590E4A1004F9CF620D8C56137D9287
+ 256'h81A3637187C027B6ACA8E4FFC89A3209A1642741192E3979E50F4B7302BF908C
};
// Compile-time random bits for owner intermediate identity seed
parameter keymgr_pkg::seed_t RndCnstKeymgrOwnerIntIdentitySeed = {
- 256'h32949CC3635D1F47C8F05AFFC85F7D889ECD94B67EB674BBDF38D62D3622493
+ 256'hDC165280C0509A5CBEE310112A22E896651CDF06599BF6FFC17FFF937DE17023
};
// Compile-time random bits for owner identity seed
parameter keymgr_pkg::seed_t RndCnstKeymgrOwnerIdentitySeed = {
- 256'hEEC5E43D4B16446726A27B8F0B30AD5048BAE844C87B69111A24D5E4442BCFB7
+ 256'h36C5B3D0A873F50B0E273058CAA5291BD06F88A44B8243CA1A45B215CC7256C
};
// Compile-time random bits for software generation seed
parameter keymgr_pkg::seed_t RndCnstKeymgrSoftOutputSeed = {
- 256'hAB174A27F3E9A7DA096F534D1A07EB42A37DBFB7BE9BB6E69A7D3C5F369AE283
+ 256'h44AF7C286396D54F33CEB281D957BF9ED89305D88D8D71C2CA6258CC000DA006
};
// Compile-time random bits for hardware generation seed
parameter keymgr_pkg::seed_t RndCnstKeymgrHardOutputSeed = {
- 256'h8FEFBC18548DFCB2FD145395D417DF2F55255E182EFED724CF8370466A266421
+ 256'hF085D06D98C25574D82449E1AFA2201F312EA264F507A75D5B610152D8465246
};
// Compile-time random bits for generation seed when aes destination selected
parameter keymgr_pkg::seed_t RndCnstKeymgrAesSeed = {
- 256'hE390FCE7275F3BCE5145A3B8EDB5F33FD64E96A5B7A45278102F4C28F70A5B08
+ 256'hED2E99906A4AFBD4DEDB5CC59EF74E5AB14D5B983DD7598AF12E48C599DA1605
};
// Compile-time random bits for generation seed when hmac destination selected
parameter keymgr_pkg::seed_t RndCnstKeymgrHmacSeed = {
- 256'h5F0E50F0C4CDF307B6CF85BD7669C05B0E5DBC9627C050E4936E54CC761467E
+ 256'h198A2B804DF44B9E44E1C905DCD81E3B8ADCF2EA1EB87424E51CAA14DBFBEC75
};
// Compile-time random bits for generation seed when kmac destination selected
parameter keymgr_pkg::seed_t RndCnstKeymgrKmacSeed = {
- 256'hC19175299F2746EA860D6C0DD7A42245F8E1D251D66CEF31BCE5F18F586239C4
+ 256'h710581E83789A7B90140C94645887A4457E74CD0C4CCA056411C89563D15B47B
};
// Compile-time random bits for generation seed when no destination selected
parameter keymgr_pkg::seed_t RndCnstKeymgrNoneSeed = {
- 256'h350BB6B68440934DCB834F93689FE9E88EBD53404A1D7296F0CBDB8B82989AA7
+ 256'hA2415E162F57F8AA2CCE101E080C3A9DB8CA70B49D1050C47FA9CE86F3443C8C
};
////////////////////////////////////////////
@@ -191,12 +191,12 @@
////////////////////////////////////////////
// Compile-time random reset value for SRAM scrambling key.
parameter otp_ctrl_pkg::sram_key_t RndCnstSramCtrlMainSramKey = {
- 128'hB6D4B556D89F9DFCFABD19450B238D4C
+ 128'hD0EC61B1BDCBC0E305B5E826EF06FF71
};
// Compile-time random reset value for SRAM scrambling nonce.
parameter otp_ctrl_pkg::sram_nonce_t RndCnstSramCtrlMainSramNonce = {
- 64'h160733E752CAD615
+ 64'h3E4EF606D8CEFA03
};
endpackage : top_earlgrey_rnd_cnst_pkg
diff --git a/util/topgen/merge.py b/util/topgen/merge.py
index 099e2b1..3ff5ef4 100644
--- a/util/topgen/merge.py
+++ b/util/topgen/merge.py
@@ -8,8 +8,10 @@
from copy import deepcopy
from functools import partial
from math import ceil, log2
+from typing import Dict, List
from topgen import c, lib
+from reggen.ip_block import IpBlock
from reggen.params import LocalParam, Parameter, RandParameter
@@ -35,12 +37,46 @@
return literal_str
-def amend_ip(top, ip):
- """ Amend additional information into top module
+def elaborate_instances(top, blocks: List[IpBlock]):
+ '''Add additional fields to the elements of top['module']
+
+ These elements represent instantiations of IP blocks. This function adds
+ extra fields to them to carry across information from the IpBlock objects
+ that represent the blocks being instantiated. See elaborate_instance for
+ more details of what gets added.
+
+ '''
+ name_to_block = {} # type: Dict[str, IpBlock]
+ for block in blocks:
+ lblock = block.name.lower()
+ assert lblock not in name_to_block
+ name_to_block[lblock] = block
+
+ # Initialize RNG for compile-time netlist constants.
+ random.seed(int(top['rnd_cnst_seed']))
+
+ # Find the alert handler and extract the name of its clock
+ alert_clock = None
+ for instance in top['module']:
+ if instance['type'].lower() == 'alert_handler':
+ alert_clock = instance['clock_srcs']['clk_i']
+ break
+ assert alert_clock is not None
+
+ for instance in top['module']:
+ block = name_to_block[instance['type']]
+ elaborate_instance(instance, block, alert_clock)
+
+
+def elaborate_instance(instance, block: IpBlock, alert_clock: str):
+ """Add additional fields to a single instance of a module.
+
+ instance is the instance to be filled in. block is the block that it's
+ instantiating. alert_clock is the name of the clock signal used for the
+ alert handler.
Amended fields:
- size: register space
- - clock: converted into ip_clock
- bus_device
- bus_host: none if doesn't exist
- available_input_list: empty list if doesn't exist
@@ -50,152 +86,138 @@
- interrupt_list: empty list if doesn't exist
- alert_list: empty list if doesn't exist
- wakeup_list: empty list if doesn't exist
+
"""
- ip_list_in_top = [x["type"].lower() for x in top["module"]]
- # TODO make set
- ipname = ip.name.lower()
- if ipname not in ip_list_in_top:
- log.info("TOP doens't use the IP %s. Skip" % ip.name)
- return
+ mod_name = instance["name"]
- # Initialize RNG for compile-time netlist constants.
- random.seed(int(top['rnd_cnst_seed']))
+ # Fill in the size field if it's missing. If it existed already, check that
+ # there's enough space for the block.
+ min_size = 1 << block.regs.get_addr_width()
+ dflt_size = max(min_size, 0x1000)
+ decl_size = instance.get('size')
+ if decl_size is None:
+ instance['size'] = '{:#x}'.format(dflt_size)
+ else:
+ if int(decl_size, 0) < min_size:
+ log.error("Instance {} of block {} has a size field of {}, but"
+ "the block needs at least {} bytes."
+ .format(mod_name, block.name, decl_size, min_size))
- # Needed to detect async alert transitions below
- ah_idx = ip_list_in_top.index("alert_handler")
+ instance["bus_device"] = block.bus_device or 'none'
+ instance["bus_host"] = block.bus_host or 'none'
- # Find multiple IPs
- # Find index of the IP
- ip_modules = list(
- filter(lambda module: module["type"] == ipname, top["module"]))
+ inouts, inputs, outputs = block.xputs
+ instance['available_inout_list'] = [
+ {'name': signal.name,
+ 'width': signal.bits.width(),
+ 'type': 'inout'}
+ for signal in inouts
+ ]
+ instance['available_input_list'] = [
+ {'name': signal.name,
+ 'width': signal.bits.width(),
+ 'type': 'input'}
+ for signal in inputs
+ ]
+ instance['available_output_list'] = [
+ {'name': signal.name,
+ 'width': signal.bits.width(),
+ 'type': 'output'}
+ for signal in outputs
+ ]
- ip_size = 1 << ip.regs.get_addr_width()
+ # param_list
+ new_params = []
+ for param in block.params.by_name.values():
+ if isinstance(param, LocalParam):
+ # Remove local parameters.
+ continue
- for ip_module in ip_modules:
- mod_name = ip_module["name"]
+ new_param = param.as_dict()
- # Size
- if "size" not in ip_module:
- ip_module["size"] = "0x%x" % max(ip_size, 0x1000)
- elif int(ip_module["size"], 0) < ip_size:
- log.error(
- "given 'size' field in IP %s is smaller than the required space"
- % mod_name)
+ param_expose = param.expose if isinstance(param, Parameter) else False
- ip_module["bus_device"] = ip.bus_device or 'none'
- ip_module["bus_host"] = ip.bus_host or 'none'
+ # Check for security-relevant parameters that are not exposed,
+ # adding a top-level name.
+ if param.name.lower().startswith("sec") and not param_expose:
+ log.warning("{} has security-critical parameter {} "
+ "not exposed to top".format(
+ mod_name, param.name))
- inouts, inputs, outputs = ip.xputs
- ip_module['available_inout_list'] = [
- {'name': signal.name,
- 'width': signal.bits.width(),
- 'type': 'inout'}
- for signal in inouts
- ]
- ip_module['available_input_list'] = [
- {'name': signal.name,
- 'width': signal.bits.width(),
- 'type': 'input'}
- for signal in inputs
- ]
- ip_module['available_output_list'] = [
- {'name': signal.name,
- 'width': signal.bits.width(),
- 'type': 'output'}
- for signal in outputs
- ]
+ # Move special prefixes to the beginnining of the parameter name.
+ param_prefixes = ["Sec", "RndCnst"]
+ cc_mod_name = c.Name.from_snake_case(mod_name).as_camel_case()
+ name_top = cc_mod_name + param.name
+ for prefix in param_prefixes:
+ if param.name.lower().startswith(prefix.lower()):
+ name_top = (prefix + cc_mod_name +
+ param.name[len(prefix):])
+ break
- # param_list
- new_params = []
- for param in ip.params.by_name.values():
- if isinstance(param, LocalParam):
- # Remove local parameters.
- continue
+ new_param['name_top'] = name_top
- new_param = param.as_dict()
+ # Generate random bits or permutation, if needed
+ if isinstance(param, RandParameter):
+ if param.randtype == 'data':
+ new_default = _get_random_data_hex_literal(param.randcount)
+ # Effective width of the random vector
+ randwidth = param.randcount
+ else:
+ assert param.randtype == 'perm'
+ new_default = _get_random_perm_hex_literal(param.randcount)
+ # Effective width of the random vector
+ randwidth = param.randcount * ceil(log2(param.randcount))
- param_expose = param.expose if isinstance(param, Parameter) else False
+ new_param['default'] = new_default
+ new_param['randwidth'] = randwidth
- # Check for security-relevant parameters that are not exposed,
- # adding a top-level name.
- if param.name.lower().startswith("sec") and not param_expose:
- log.warning("{} has security-critical parameter {} "
- "not exposed to top".format(
- mod_name, param.name))
+ new_params.append(new_param)
- # Move special prefixes to the beginnining of the parameter name.
- param_prefixes = ["Sec", "RndCnst"]
- cc_mod_name = c.Name.from_snake_case(mod_name).as_camel_case()
- name_top = cc_mod_name + param.name
- for prefix in param_prefixes:
- if param.name.lower().startswith(prefix.lower()):
- name_top = (prefix + cc_mod_name +
- param.name[len(prefix):])
- break
+ instance["param_list"] = new_params
- new_param['name_top'] = name_top
+ # interrupt_list
+ instance["interrupt_list"] = [
+ {'name': i.name,
+ 'width': i.bits.width(),
+ 'type': 'interrupt'}
+ for i in block.interrupts
+ ]
- # Generate random bits or permutation, if needed
- if isinstance(param, RandParameter):
- if param.randtype == 'data':
- new_default = _get_random_data_hex_literal(param.randcount)
- # Effective width of the random vector
- randwidth = param.randcount
- else:
- assert param.randtype == 'perm'
- new_default = _get_random_perm_hex_literal(param.randcount)
- # Effective width of the random vector
- randwidth = param.randcount * ceil(log2(param.randcount))
+ # alert_list. An alert is considered asynchronous if the clock name for the
+ # instance's clk_i doesn't match alert_clock (which is the clock name for
+ # the alert handler's clk_i).
+ async_alerts = (instance["clock_srcs"]["clk_i"] != alert_clock)
+ instance["alert_list"] = [
+ {'name': i.name,
+ 'type': 'alert',
+ 'width': 1,
+ 'async': '1' if async_alerts else '0'}
+ for i in block.alerts
+ ]
- new_param['default'] = new_default
- new_param['randwidth'] = randwidth
+ # wkup_list
+ instance["wakeup_list"] = [
+ {'name': signal.name,
+ 'width': str(signal.bits.width())}
+ for signal in block.wakeups
+ ]
- new_params.append(new_param)
+ # reset request
+ instance["reset_request_list"] = [
+ {'name': signal.name,
+ 'width': str(signal.bits.width())}
+ for signal in block.reset_requests
+ ]
- ip_module["param_list"] = new_params
+ # scan
+ instance['scan'] = 'true' if block.scan else 'false'
- # interrupt_list
- ip_module["interrupt_list"] = [
- {'name': i.name,
- 'width': i.bits.width(),
- 'type': 'interrupt'}
- for i in ip.interrupts
- ]
+ # scan_reset
+ instance['scan_reset'] = 'true' if block.scan_reset else 'false'
- # alert_list
- async_alerts = (ip_module["clock_srcs"]["clk_i"] !=
- top["module"][ah_idx]["clock_srcs"]["clk_i"])
- ip_module["alert_list"] = [
- {'name': i.name,
- 'type': 'alert',
- 'width': 1,
- 'async': '1' if async_alerts else '0'}
- for i in ip.alerts
- ]
-
- # wkup_list
- ip_module["wakeup_list"] = [
- {'name': signal.name,
- 'width': str(signal.bits.width())}
- for signal in ip.wakeups
- ]
-
- # reset request
- ip_module["reset_request_list"] = [
- {'name': signal.name,
- 'width': str(signal.bits.width())}
- for signal in ip.reset_requests
- ]
-
- # scan
- ip_module['scan'] = 'true' if ip.scan else 'false'
-
- # scan_reset
- ip_module['scan_reset'] = 'true' if ip.scan_reset else 'false'
-
- # inter-module
- ip_module["inter_signal_list"] = ip.inter_signals.copy()
- # TODO: validate
+ # inter-module
+ instance["inter_signal_list"] = block.inter_signals.copy()
+ # TODO: validate
# TODO: Replace this part to be configurable from Hjson or template
@@ -928,47 +950,46 @@
format(e))
-def merge_top(topcfg: OrderedDict, ipobjs: OrderedDict,
+def merge_top(topcfg: OrderedDict,
+ blocks: List[IpBlock],
xbarobjs: OrderedDict) -> OrderedDict:
- gencfg = topcfg
# Combine ip cfg into topcfg
- for ip in ipobjs:
- amend_ip(gencfg, ip)
+ elaborate_instances(topcfg, blocks)
# Create clock connections for each block
# Assign clocks into appropriate groups
- # Note, amend_ip references clock information to establish async handling
+ # Note, elaborate_instances references clock information to establish async handling
# as part of alerts.
- # amend_clocks(gencfg)
+ # amend_clocks(topcfg)
# Combine the wakeups
- amend_wkup(gencfg)
- amend_reset_request(gencfg)
+ amend_wkup(topcfg)
+ amend_reset_request(topcfg)
# Combine the interrupt (should be processed prior to xbar)
- amend_interrupt(gencfg)
+ amend_interrupt(topcfg)
# Combine the alert (should be processed prior to xbar)
- amend_alert(gencfg)
+ amend_alert(topcfg)
# Creates input/output list in the pinmux
log.info("Processing PINMUX")
- amend_pinmux_io(gencfg)
+ amend_pinmux_io(topcfg)
# Combine xbar into topcfg
for xbar in xbarobjs:
- amend_xbar(gencfg, xbar)
+ amend_xbar(topcfg, xbar)
# 2nd phase of xbar (gathering the devices address range)
- for xbar in gencfg["xbar"]:
- xbar_cross(xbar, gencfg["xbar"])
+ for xbar in topcfg["xbar"]:
+ xbar_cross(xbar, topcfg["xbar"])
# Add path names to declared resets.
# Declare structure for exported resets.
- amend_resets(gencfg)
+ amend_resets(topcfg)
# remove unwanted fields 'debug_mem_base_addr'
- gencfg.pop('debug_mem_base_addr', None)
+ topcfg.pop('debug_mem_base_addr', None)
- return gencfg
+ return topcfg