@@ -499,6 +499,10 @@ def get_neurosim_output(
499499 cell size.
500500 """
501501 )
502+
503+ # pJ->J, um^2->m^2
504+ rval = {k : v / 1e12 for k , v in rval .items ()}
505+
502506 return rval
503507
504508 def query_neurosim (self , kind : str , logger : logging .Logger ) -> Dict [str , float ]:
@@ -1398,156 +1402,6 @@ def build_crossbar(
13981402 return CACHE [key ]
13991403
14001404
1401- def get_neurosim_output (
1402- kind : str , attributes : dict , logger : logging .Logger
1403- ) -> Dict [str , float ]:
1404- """Queries Neurosim for the stats for 'kind' component with 'attributes' attributes"""
1405- assert kind in SUPPORTED_CLASSES , f"Unsupported primitive: { kind } "
1406- logger .debug ("Querying Neurosim for %s with attributes: %s" , kind , attributes )
1407-
1408- # Load defaults
1409- to_pass = {k : v [1 ] for k , v in ALL_PARAMS .items ()}
1410- # Get call function ready
1411- callfunc = SUPPORTED_CLASSES [kind ][0 ]
1412- params = SUPPORTED_CLASSES [kind ][1 ]
1413- docs = {k : v [0 ] for k , v in params .items ()}
1414-
1415- # Get required parameters
1416- for p in params :
1417- if "REQUIRED" in params [p ][0 ]:
1418- assert p in attributes , (
1419- f"Failed to generate { kind } . Required parameter not found: "
1420- f"{ p } . Usage: \n { dict_to_str (docs )} "
1421- )
1422- elif p not in attributes :
1423- attributes [p ] = to_pass [p ]
1424-
1425- passtype = params [p ][2 ] if len (params [p ]) > 2 else int
1426- try :
1427- if isinstance (attributes [p ], str ) and passtype != str :
1428- t = "" .join (c for c in attributes [p ] if (c .isdigit () or c == "." ))
1429- else :
1430- t = attributes [p ]
1431- if t != attributes [p ]:
1432- logger .warning (
1433- f"WARN: Non-numeric { attributes [p ]} for parameter { p } . Using { t } instead."
1434- )
1435- to_pass [p ] = passtype (t )
1436- except ValueError as e :
1437- raise ValueError (
1438- f"Failed to generate { kind } . Parameter { p } must be of type "
1439- f'{ passtype } . Given: "{ attributes [p ]} " Usage: \n { dict_to_str (docs )} '
1440- ) from e
1441-
1442- tn = PERMITTED_TECH_NODES
1443- assert to_pass ["rows" ] >= 8 , f'Rows must be >=8. Got { to_pass ["rows" ]} '
1444- assert to_pass ["cols" ] >= 8 , f'Columns must be >=8. Given: { to_pass ["columns" ]} '
1445- assert to_pass ["cols_active_at_once" ] >= 1 , (
1446- f"Columns active at once must be >=1 and divide evenly into cols. "
1447- f'Given: { to_pass ["cols" ]} cols, { to_pass ["cols_active_at_once" ]} cols active at once'
1448- )
1449- assert (
1450- min (tn ) <= to_pass ["tech_node" ] <= max (tn )
1451- ), f'Tech node must be between { max (tn )} and { min (tn )} . Given: { to_pass ["tech_node" ]} '
1452- assert (
1453- to_pass ["n_bits" ] >= 1
1454- ), f'Adder resolution must be >=1. Given: { to_pass ["n_bits" ]} '
1455- assert (
1456- to_pass ["shift_register_n_bits" ] >= 1
1457- ), f'Shift register resolution must be >=1. Given: { to_pass ["shift_register_n_bits" ]} '
1458- assert (
1459- to_pass ["pool_window" ] >= 1
1460- ), f'Max pool window size must be >=1. Given: { to_pass ["window_size" ]} '
1461- assert (
1462- to_pass ["n_adder_tree_inputs" ] > 0
1463- ), f'Number of adder tree inputs must be >=1. Given: { to_pass ["n_adder_tree_inputs" ]} '
1464- assert (
1465- to_pass ["n_mux_inputs" ] > 0
1466- ), f'Number of mux inputs must be >=1. Given: { to_pass ["n_mux_inputs" ]} '
1467- assert (
1468- to_pass ["voltage_dac_bits" ] > 0
1469- ), f'Voltage DAC bits must be >=1. Given: { to_pass ["voltage_dac_bits" ]} '
1470- assert (
1471- to_pass ["temporal_dac_bits" ] > 0
1472- ), f'Temporal DAC bits must be >=1. Given: { to_pass ["temporal_dac_bits" ]} '
1473-
1474- if not os .path .exists (to_pass ["cell_config" ]):
1475- cell_config = os .path .join (
1476- SCRIPT_DIR , "cells" , to_pass ["cell_config" ] + ".cell"
1477- )
1478- assert os .path .exists (cell_config ), (
1479- f'Cell config { to_pass ["cell_config" ]} " not found. '
1480- f'Try a sample config: "{ ", " .join (SAMPLE_CELLS )} '
1481- )
1482- to_pass ["cell_config" ] = cell_config
1483-
1484- # Interpolate the tech_node node. If p is in PERMITTED_TECH_NODES, then all this
1485- # comes out to just p. If p is not in PERMITTED_TECH_NODES, then we interpolate
1486- # between the two closest.
1487- t = to_pass ["tech_node" ]
1488- del to_pass ["tech_node" ]
1489-
1490- for k in attributes :
1491- if k not in to_pass :
1492- to_pass [k ] = attributes [k ]
1493-
1494- hi = min (p for p in PERMITTED_TECH_NODES if p >= t )
1495- lo = max (p for p in PERMITTED_TECH_NODES if p <= t )
1496- interp_pt = (t - lo ) / (hi - lo ) if hi - lo else 0
1497- hi_crossbar = build_crossbar (to_pass , logger , overrides = {"tech_node" : hi })
1498- lo_crossbar = build_crossbar (to_pass , logger , overrides = {"tech_node" : lo })
1499- hi_est = callfunc (
1500- hi_crossbar , to_pass ["average_input_value" ], to_pass ["average_cell_value" ]
1501- )
1502- lo_est = callfunc (
1503- lo_crossbar , to_pass ["average_input_value" ], to_pass ["average_cell_value" ]
1504- )
1505- if hi != lo :
1506- logger .debug (
1507- "Interpolating between %s and %s. Interpolation " "point: %s" ,
1508- lo ,
1509- hi ,
1510- interp_pt ,
1511- )
1512-
1513- rval = {k : lo_est [k ] + (hi_est [k ] - lo_est [k ]) * interp_pt for k in hi_est }
1514- logger .debug ("NeuroSim returned: %s" , rval )
1515-
1516- assert rval ["Area" ] >= 0 , dedent (
1517- """
1518- NeuroSim returned an area less than zero. This may occur if the array or
1519- memory cell size is too small for proper layout of peripheral
1520- components. Try increasing the number of rows/columns or increasing the
1521- cell size.
1522- """
1523- )
1524-
1525- return rval
1526-
1527-
1528- def query_neurosim (
1529- kind : str , attributes : dict , logger : logging .Logger
1530- ) -> Dict [str , float ]:
1531- for n in ["array_adc" , "array_col_drivers" ]:
1532- assert (
1533- n in SUPPORTED_CLASSES
1534- ), "Please update this method body to support the new NeuroSim names."
1535-
1536- if kind == "array_col_drivers" :
1537- attributes ["adc_resolution" ] = 0
1538- return get_neurosim_output (kind , attributes , logger )
1539-
1540- if kind in ["array_adc" , "array_col_drivers" ]:
1541- logger .info ("First running WITH the ADC to get total energy" )
1542- with_adc = get_neurosim_output (kind , attributes , logger )
1543- attributes ["adc_resolution" ] = 0
1544- logger .info ("Now running WITHOUT the ADC to get column driver energy" )
1545- without_adc = get_neurosim_output (kind , attributes , logger )
1546- logger .info ("Subtracting column driver energy to get ADC energy" )
1547- return {k : with_adc [k ] - without_adc [k ] for k in with_adc }
1548- return get_neurosim_output (kind , attributes , logger )
1549-
1550-
15511405def dict_to_str (attributes : Dict ) -> str :
15521406 """Converts a dictionary into a multi-line string representation"""
15531407 s = "\n "
0 commit comments