Skip to content

Commit

Permalink
vendor.gowin: Only use 'part' and 'family' to identify device. Add pa…
Browse files Browse the repository at this point in the history
…rse_part method to validate input and extract information.
  • Loading branch information
bl0x committed Aug 7, 2023
1 parent c003030 commit cba831b
Showing 1 changed file with 48 additions and 22 deletions.
70 changes: 48 additions & 22 deletions amaranth/vendor/gowin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from abc import abstractproperty
from fractions import Fraction
from re import search

from ..hdl import *
from ..lib.cdc import ResetSynchronizer
Expand Down Expand Up @@ -41,28 +42,51 @@ class GowinPlatform(TemplatedPlatform):

toolchain = None # selected when creating platform

series = abstractproperty()
subseries = abstractproperty()
voltage = abstractproperty()
size = abstractproperty()
package = abstractproperty()
speed = abstractproperty()
part = abstractproperty()
family = abstractproperty()

@property
def _part(self):
return "{}-{}{}{}{}".format(self.series, self.voltage, self.size, self.package, self.speed)
def parse_part(self):
# These regular expressions match all >900 parts of Gowin device_info.csv
reg_series = "(GW[12]{1}[AN]{1}[EFNRSZ]{0,3})-"
reg_voltage = "(ZV|EV|LV|LX|UV|UX)"
reg_size = "(1|2|4|9|18|55)"
reg_subseries = "(?:(B|C|S|X|P5)?)"
reg_package = "((?:PG|UG|EQ|LQ|MG|M|QN|CS|FN)(?:\d+)(?:P?)(?:A|E|M|CF|C|D|G|H|F|S|T|U|X)?)"
reg_speed = "((?:C\d{1}/I\d{1})|ES|A\d{1}|I\d{1})"

@property
def _device_name(self):
return "{}-{}{}".format(self.series, self.size, self.subseries)
match = search(reg_series+reg_voltage+reg_size+reg_subseries+reg_package+reg_speed, self.part)
if len(match.groups()) != 6:
raise ValueError("Supplied part name is invalid.")

self.series = match.group(1)
self.voltage = match.group(2)
self.size = match.group(3)
self.subseries = match.group(4) or ""
self.package = match.group(5)
self.speed = match.group(6)

match = search(reg_series+reg_size+reg_subseries, self.family)
if len(match.groups()) != 3:
raise ValueError("Supplied device family name is invalid.")

self.series_f = match.group(1)
self.size_f = match.group(2)
self.subseries_f = match.group(3) or ""

# subseries_f is usually more reliable than subseries.

if self.series != self.series_f:
raise ValueError("Series extracted from supplied part name does not match supplied family series")
if self.size != self.size_f:
raise ValueError("Size extracted from supplied part name does not match supplied family size")

# _chipdb_device is tied to available chipdb-*.bin files of nextpnr-gowin
@property
def _chipdb_device(self):
# GW1NR series does not have its own chipdb file, but works with GW1N
if self.series == "GW1NR":
return "GW1N-{}{}".format(self.size, self.subseries)
return self._device_name
return "GW1N-{}{}".format(self.size, self.subseries_f)
return self.family

_dev_osc_mapping = {
"GW1N-1" : "OSCH",
Expand Down Expand Up @@ -109,21 +133,21 @@ def _chipdb_device(self):

@property
def _osc_type(self):
if self._device_name in self._dev_osc_mapping:
return self._dev_osc_mapping[self._device_name]
raise NotImplementedError("Device {} does not have an assigned oscillator type"
.format(self._device_name))
if self.family in self._dev_osc_mapping:
return self._dev_osc_mapping[self.family]
raise NotImplementedError("Device family {} does not have an assigned oscillator type"
.format(self.family))

@property
def _osc_base_freq(self):
osc = self._osc_type
if osc == "OSC":
if self._device_name.endswith(("-4", "-4B", "-4D")):
if self.speed == 4 and self.subseries_f in ("B", "D"):
return 210_000_000
else:
return 250_000_000
elif osc in ("OSCZ", "OSCO"):
if self._device_name.startswith("GW1NSR") and self.speed == "C7":
if self.series == "GW1NSR" and self.speed == "C7/I6":
return 260_000_000
else:
return 250_000_000
Expand Down Expand Up @@ -213,7 +237,7 @@ def _osc_div(self):
{{quiet("--quiet")}}
{{get_override("nextpnr_opts")|options}}
--log {{name}}.tim
--device {{platform._part}}
--device {{platform.part}}
--family {{platform._chipdb_device}}
--json {{name}}.json
--cst {{name}}.cst
Expand Down Expand Up @@ -246,7 +270,7 @@ def _osc_div(self):
add_file -type verilog {{name}}.v
add_file -type cst {{name}}.cst
add_file -type sdc {{name}}.sdc
set_device -name {{platform._device_name}} {{platform._part}}
set_device -name {{platform.family}} {{platform.part}}
set_option -verilog_std v2001 -print_all_synthesis_warning 1 -show_all_warn 1
{{get_override("add_options")|default("# (add_options placeholder)")}}
run all
Expand Down Expand Up @@ -274,6 +298,8 @@ def __init__(self, *, toolchain="Apicula"):
assert toolchain in ("Apicula", "Gowin")
self.toolchain = toolchain

self.parse_part()

@property
def required_tools(self):
if self.toolchain == "Apicula":
Expand Down

0 comments on commit cba831b

Please sign in to comment.