This commit fixes the issue with the user ID programming block not

getting changed by "make ship" because the build is done in a place
where the path pointer to the user_id_programming GDS still points
back to the original caravel repository, not the user project
repository.  The user_id_programming GDS was removed (no longer used),
the user_id_programming.mag file was modified to remove the path
pointer to the GDS, and the set_user_id.py script was modified to
make changes directly to the user_id_programming.mag file instead of
the GDS.  An additional method was added to the set_user_id.py script
to modify the gate-level verilog/gl/user_id_programming.v to make
the user ID correct for gate-level testbench simulations.
This commit is contained in:
Tim Edwards 2022-03-22 10:25:25 -04:00
parent 191139bf0e
commit 53abff5bbf
4 changed files with 60 additions and 87 deletions

View File

@ -1133,10 +1133,10 @@ __set_user_id:
mkdir -p ./signoff/build
# Update info.yaml
# sed -r "s/^(\s*project_id\s*:\s*).*/\1${USER_ID}/" -i info.yaml
cp $(CARAVEL_ROOT)/gds/user_id_programming.gds ./gds/user_id_programming.gds
cp $(CARAVEL_ROOT)/mag/user_id_programming.mag ./mag/user_id_programming.mag
cp $(CARAVEL_ROOT)/mag/user_id_textblock.mag ./mag/user_id_textblock.mag
cp $(CARAVEL_ROOT)/verilog/rtl/caravel.v ./verilog/rtl/caravel.v
cp $(CARAVEL_ROOT)/verilog/gl/user_id_programming.v ./verilog/gl/user_id_programming.v
python3 $(CARAVEL_ROOT)/scripts/set_user_id.py $(USER_ID) $(shell pwd) 2>&1 | tee ./signoff/build/set_user_id.out
.PHONY: gpio_defaults

Binary file not shown.

View File

@ -3154,6 +3154,4 @@ rlabel metal5 s 1104 2512 5980 2832 4 VGND
port 34 nsew
<< properties >>
string FIXED_BBOX 0 0 7109 7077
string GDS_FILE ../gds/user_id_programming.gds
string GDS_START 0
<< end >>

View File

@ -184,14 +184,9 @@ if __name__ == '__main__':
print('Setting project user ID to: ' + user_id_value)
magpath = user_project_path + '/mag'
gdspath = user_project_path + '/gds'
vpath = user_project_path + '/verilog'
errors = 0
if not os.path.isdir(gdspath):
print('No directory ' + gdspath + ' found (path to GDS).')
sys.exit(1)
if not os.path.isdir(vpath):
print('No directory ' + vpath + ' found (path to verilog).')
sys.exit(1)
@ -200,44 +195,24 @@ if __name__ == '__main__':
print('No directory ' + magpath + ' found (path to magic databases).')
sys.exit(1)
print('Step 1: Modify GDS of the user_id_programming subcell')
print('Step 1: Modify layout of the user_id_programming subcell')
# Bytes leading up to via position are:
viarec = "00 06 0d 02 00 43 00 06 0e 02 00 2c 00 2c 10 03 "
viabytes = bytes.fromhex(viarec)
# Check for either GDS file being gzipped
gdsbakgz = gdspath + '/user_id_prog_zero.gds.gz'
gdsfilegz = gdspath + '/user_id_programming.gds.gz'
# Read the ID programming layout. If a backup was made of the
# zero-value program, then use it.
if os.path.isfile(gdsbakgz):
subprocess.run(['gunzip', gdsbakgz],
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL)
zero_zipped = True
magbak = magpath + '/user_id_prog_zero.mag'
magfile = magpath + '/user_id_programming.mag'
if os.path.isfile(magbak):
with open(magbak, 'r') as ifile:
magdata = ifile.read()
else:
zero_zipped = False
if os.path.isfile(gdsfilegz):
subprocess.run(['gunzip', gdsfilegz],
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL)
file_zipped = True
else:
file_zipped = False
# Read the GDS file. If a backup was made of the zero-value
# program, then use it.
gdsbak = gdspath + '/user_id_prog_zero.gds'
gdsfile = gdspath + '/user_id_programming.gds'
if os.path.isfile(gdsbak):
with open(gdsbak, 'rb') as ifile:
gdsdata = ifile.read()
else:
with open(gdsfile, 'rb') as ifile:
gdsdata = ifile.read()
with open(magfile, 'r') as ifile:
magdata = ifile.read()
for i in range(0,32):
# Ignore any zero bits.
@ -256,72 +231,45 @@ if __name__ == '__main__':
xurum = xum + 0.085
yurum = yum + 0.085
# Get the 4-byte hex values for the corner coordinates
xllnm = round(xllum * 1000)
yllnm = round(yllum * 1000)
xllhex = '{0:08x}'.format(xllnm)
yllhex = '{0:08x}'.format(yllnm)
xurnm = round(xurum * 1000)
yurnm = round(yurum * 1000)
xurhex = '{0:08x}'.format(xurnm)
yurhex = '{0:08x}'.format(yurnm)
# Get the values for the corner coordinates in magic internal units
xlli = int(round(xllum * 200))
ylli = int(round(yllum * 200))
xuri = int(round(xurum * 200))
yuri = int(round(yurum * 200))
viaoldposdata = 'rect ' + xlli + ' ' + ylli + ' ' + xuri + ' ' + yuri
# Magic's GDS output for vias always starts at the lower left
# corner and goes counterclockwise, repeating the first point.
viaoldposdata = viarec + xllhex + yllhex + xurhex + yllhex
viaoldposdata += xurhex + yurhex + xllhex + yurhex + xllhex + yllhex
# For "one" bits, the X position is moved 0.92 microns to the left
newxllum = xllum - 0.92
newxurum = xurum - 0.92
# Get the 4-byte hex values for the new corner coordinates
newxllnm = round(newxllum * 1000)
newxllhex = '{0:08x}'.format(newxllnm)
newxurnm = round(newxurum * 1000)
newxurhex = '{0:08x}'.format(newxurnm)
# Get the values for the new corner coordinates in magic internal units
newxlli = int(round(newxllum * 200))
newxuri = int(round(newxurum * 200))
vianewposdata = viarec + newxllhex + yllhex + newxurhex + yllhex
vianewposdata += newxurhex + yurhex + newxllhex + yurhex + newxllhex + yllhex
vianewposdata = 'rect ' + newxlli + ' ' + ylli + ' ' + newxuri + ' ' + yuri
# Diagnostic
if debugmode:
print('Bit ' + str(i) + ':')
print('Via position ({0:3.2f}, {1:3.2f}) to ({2:3.2f}, {3:3.2f})'.format(xllum, yllum, xurum, yurum))
print('Old hex string = ' + viaoldposdata)
print('New hex string = ' + vianewposdata)
# Convert hex strings to byte arrays
viaoldbytedata = bytearray.fromhex(viaoldposdata)
vianewbytedata = bytearray.fromhex(vianewposdata)
print('Old string = "' + viaoldposdata + '"')
print('New string = "' + vianewposdata + '"')
# Replace the old data with the new
if viaoldbytedata not in gdsdata:
if viaoldposdata not in gdsdata:
print('Error: via not found for bit position ' + str(i))
errors += 1
else:
gdsdata = gdsdata.replace(viaoldbytedata, vianewbytedata)
magdata == magdata.replace(viaoldposdata, vianewposdata)
if errors == 0:
# Keep a copy of the original
if not os.path.isfile(gdsbak):
if file_zipped:
if os.path.isfile(gdsfilegz):
os.rename(gdsfilegz, gdsbakgz)
else:
os.rename(gdsfile, gdsbak)
subprocess.run(['gzip', gdsbak, '-n', '--best'],
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL)
else:
os.rename(gdsfile, gdsbak)
if not os.path.isfile(magbak):
os.rename(magfile, magbak)
with open(gdsfile, 'wb') as ofile:
ofile.write(gdsdata)
if file_zipped:
subprocess.run(['gzip', gdsfile, '-n', '--best'],
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL)
with open(magfile, 'w') as ofile:
ofile.write(magdata)
print('Done!')
@ -330,7 +278,7 @@ if __name__ == '__main__':
print('Ending process.')
sys.exit(1)
print('Step 2: Add user project ID parameter to verilog.')
print('Step 2: Add user project ID parameter to source verilog.')
changed = False
with open(vpath + '/rtl/caravel.v', 'r') as ifile:
@ -354,7 +302,34 @@ if __name__ == '__main__':
print('Ending process.')
sys.exit(1)
print('Step 3: Add user project ID text to top level layout.')
print('Step 3: Add user project ID parameter to gate-level verilog.')
changed = False
with open(vpath + '/gl/user_id_programming.v', 'r') as ifile:
vdata = ifile.read()
for i in range(0,32):
# Ignore any zero bits.
if user_id_bits[i] == '0':
continue
outdata = vdata.replace('high[' + str(i) + ']', 'XXXX')
outdata = outdata.replace('low[' + str(i) + ']', 'high[' + str(i) + ']')
outdata = outdata.replace('XXXX', 'low[' + str(i) + ']')
outdata = outdata.replace('LO(mask_rev[' + str(i) + ']',
'HI(mask_rev[' + str(i) + ']')
outdata = outdata.replace('HI(\\user_proj_id_low', 'LO(\\user_proj_id_low')
if changed:
with open(vpath + '/gl/user_id_programming.v', 'w') as ofile:
ofile.write(outdata)
print('Done!')
else:
print('Error: No substitutions done on verilog/gl/user_id_programming.v.')
print('Ending process.')
sys.exit(1)
print('Step 4: Add user project ID text to top level layout.')
with open(magpath + '/user_id_textblock.mag', 'r') as ifile:
maglines = ifile.read().splitlines()