Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Version: 0.1
The following packages is required to successfully compile and execute chipForge.

``` bash
apt install build-essencials # for compiling
apt install build-essentials # for compiling
```

### Installation
Expand Down
227 changes: 227 additions & 0 deletions README_UPDATES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# chipSmith – ViPeR compatibility fixes and quality-of-life updates

This document records the changes we made to **chipSmith** so it works cleanly inside the **ViPeR** flow and with modern LEF/DEF/GDS inputs. It also includes build notes (MSYS2/MinGW‑w64) and instructions for pushing these changes to GitHub via a fork + pull request.

---

## Summary of fixes

### 1) Config file: accept `-c <chipsmith_config.toml>` and improve errors
**Files:** `src/main.cpp` (or wherever `main` lives), `src/chipsmith/chipFill.cpp`

- Enabled the banner (`welcomeScreen()`).
- **Hard‑coded `config.toml` removed.** We now parse an optional `-c`/`--config` CLI flag and pass that filename through the tool flow. If the flag is omitted we fall back to `config.toml` for backwards compatibility.
- Added **strict/clear error messages** when required top‑level tables are missing from the config, printing the available keys before exiting.

**Why:** The ViPeR flow provides a `chipsmith_config.toml` separate from the top‑level `config.toml`. The original chipSmith always tried to read `config.toml`, producing confusing errors.

---

### 2) Read ViPeR’s new TOML keys and translate to chipSmith’s internal structures
**File:** `src/chipsmith/chipFill.cpp`

- We still read the original chipSmith tables:
- `[GDS_CELL_LOCATIONS]`
- `[GDS_MAIN_STR_NAME]`
- `[GDS_LOCATIONS]`
- **New:** we now parse **`[Biasing_Coordinate.*]`** (ViPeR style) and translate it into the legacy `GateBiasCorX` map that `placeBias()` uses.
- For each block (e.g. `[Biasing_Coordinate.AND2T]`), we take the first element of `top = [<x>]` as the bias x‑offset (in microns).
- We map the logical gate name (`AND2T`) to the actual GDS main structure name via `[GDS_MAIN_STR_NAME]` (e.g. `LSmitll_AND2T_v2p1`).

- **Layer name normalization for routing:** DEFs may emit `metal1`, `metal2`, etc. ViPeR’s `[Parameters]` contains
```toml
routingLayers = ["M1", "M3"]
```
We now route:
- `metal1` → GDS layer **10** (M1)
- `metal2` → GDS layer **30** (M3)
The PTL width comes from `Parameters.PTLwidth` (µm) and is converted to GDS units.

**Why:** Without these translations, no top‑level routing appeared (DEF layer names didn’t match the original hard‑coded mapping), and `placeBias()` couldn’t find x‑offsets for modern config files.

---

### 3) **Via import decoupled from fill enable** (critical bug fix)
**Files:** `src/chipsmith/chipFill.cpp`

- Previously, the via cell **`ViaM1M3`** lived in `[GDS_LOCATIONS]` (with the fill cells) and was only imported when `fill = true`.
But we always place via **SREFs** regardless of `fill`. Result: GDS had references to `ViaM1M3` but no cell definition → vias appeared as **“(ViaM1M3)”** (empty) in KLayout.

- **Fix:** We always call `importFill()` (which imports everything in `[GDS_LOCATIONS]`) and guard only the *placement* step (`placeFill()`) with `fillEnable`.
This guarantees the via cell definition is present even when fill is disabled.

**Why:** Ensures via geometry is visible in the final GDS without forcing users to enable metal fill.

---

### 4) Build fixes for MSYS2/MinGW‑w64
**Files:** `include/gdscpp/gdsParser.hpp`, `src/gdscpp/gdsCpp.cpp` (and any file using fixed‑width integer types)

- Added the missing header:
```cpp
#include <cstdint>
```
to fix `'uint32_t'/'uint64_t' was not declared` errors.
- (Optional) You can statically link libstdc++/libgcc if you need a standalone EXE (larger file). The dynamic build is smaller and loads the runtime DLLs from the toolchain.

**Why:** Current GCC requires `<cstdint>` when using fixed‑width integer types.

---

### 5) Quality‑of‑life
- Printed the **units and grid summary** during `importData()`.
- Parsed the `configFileUnits` and `gdsUnits` parameters from `chipsmith_config.toml` to replace hardcoded geometry scaling parameters in `chipFill.cpp`.
- Improved consistency of console logging (clearly separates **import**, **routing**, **biasing**, **write** stages).
- Kept the original via placement logic (SREFs at DEF via sites) but ensured the via cell is always available (see §3).

---

## What changed exactly (by file)

> File paths below follow the typical tree in this repo. Adjust if your tree differs.

### `src/main.cpp`
- Enable banner.
- Parse `-c/--config` and pass filename forward (default `config.toml`).

### `src/chipsmith/chipFill.cpp`
- **`importData()`**
- Read `chipsmith_config.toml` (or user-specified file).
- Helper `expectTopTable()` prints clear error messages when required TOML tables are missing.
- Load legacy maps: `GDS_CELL_LOCATIONS`, `GDS_MAIN_STR_NAME`, `GDS_LOCATIONS`.
- Translate `[Biasing_Coordinate.*]` into `GateBiasCorX` (map from GDS main structure name → x‑offset).
- Read `Parameters` values used by chipSmith (`fill`, `fillCor`, `gateHeights`, `PTLwidth`, `gridSize`) and ViPeR‑specific routing info (`routingLayers`).

- **`toGDS()`**
- Always call `importFill()` (imports via and fill cell definitions).
- Guard only `placeFill()` with `fillEnable` (so no fill is drawn unless requested).

- **`placeNets()`**
- Map DEF layer names (`metal1`, `metal2`) to configured metals (`M1`, `M3`) and emit paths on the corresponding GDS layers (10/30).
- Leave via placement as SREFs to `"ViaM1M3"`; since `importFill()` always runs, the cell is defined and visible in KLayout.

### `include/gdscpp/gdsParser.hpp` and `src/gdscpp/gdsCpp.cpp`
- Add `#include <cstdint>` to compile on current GCC/MinGW.

> **Note:** We intentionally did **not** change the LEF parser semantics except to accept modern files that start with `VERSION 5.8 ;`. The parser now ignores the `VERSION` line rather than treating it as a fatal error.

---

## MSYS2 / MinGW‑w64 build instructions (Windows)

1. **Install MSYS2** and open the **MinGW‑w64 UCRT64** (or MINGW64) shell.
2. Install toolchain (if not already):
```bash
pacman -S --needed mingw-w64-ucrt-x86_64-toolchain cmake git
# or: mingw-w64-x86_64-toolchain
```
3. **Configure and build**:
```bash
git clone https://github.com/<your-user>/chipSmith.git
cd chipSmith
cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
```
The executable will land in `build/` (or per your CMake config).

4. (Optional) **Static link** for a self-contained EXE:
```bash
cmake -S . -B build-static -G "MinGW Makefiles" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_EXE_LINKER_FLAGS="-static -static-libgcc -static-libstdc++"
cmake --build build-static -j
```

---

## How to run chipSmith in the ViPeR flow

From the ViPeR project directory (the one with `chipsmith_config.toml`):
```bash
chipSmith -c chipsmith_config.toml
```
You should see:
- Components placed
- Nets routed on the expected layers (M1/M3 → GDS 10/30)
- Bias grid added
- **ViaM1M3** polygons visible in KLayout (cell **without** parentheses)

The output GDS is written to `out/<top>.gds` (e.g., `out/RCA16.gds`).

---

## Contributing your changes via GitHub (fork + PR)

Below are the canonical steps to fork upstream and submit your patch.

1. **Fork** the upstream repo in your browser:
Go to <https://github.com/judefdiv/chipSmith> and click **Fork**. This creates `https://github.com/<your-user>/chipSmith`.

2. **Clone your fork** locally:
```bash
git clone https://github.com/<your-user>/chipSmith.git
cd chipSmith
```

3. **Add the upstream remote** so you can sync with the original later:
```bash
git remote add upstream https://github.com/judefdiv/chipSmith.git
git fetch upstream
```

4. **Create a feature branch** for your work:
```bash
git checkout -b viper-compat-and-via-import
```

5. **Copy/commit your changes** (replace paths as needed):
```bash
# stage modified files
git add src/main.cpp \
src/chipsmith/chipFill.cpp \
include/gdscpp/gdsParser.hpp \
src/gdscpp/gdsCpp.cpp \
README.md

git commit -m "ViPeR compatibility: config switch (-c), robust TOML parsing, DEF->GDS layer mapping, always import via cell (decouple from fill), MSYS2 build fixes"
```

6. **Push** to your fork:
```bash
git push -u origin viper-compat-and-via-import
```

7. **Open a Pull Request**:
Visit your fork on GitHub; it will offer a **“Compare & pull request”** button.
In the PR description, include a concise summary (you can paste from this README).

8. (Optional) **Sync later with upstream**:
```bash
git checkout main
git fetch upstream
git merge upstream/main
git push origin main
```

---

## Regression checks

- **LEF import**: files starting with `VERSION 5.8 ;` no longer fail the dictionary check.
- **DEF routing**: `metal1`/`metal2` appear on GDS layers 10/30 with the width from `Parameters.PTLwidth`.
- **Vias**: `ViaM1M3` is a **defined** cell (not in parentheses) and the polygons are visible.
- **Fill off**: Setting `Parameters.fill=false` suppresses fill placement but **keeps via geometry** (cell import is unconditional).

---

## Known limitations / future work

- `VIA_DEFINITIONS` / `VIA_STRATEGY` are parsed in the config but are not yet used to *select different via cells*. We still place `ViaM1M3` (as the current designs do). Extending `placeNets()` to pick cell names using these tables is straightforward if/when needed.
- Layer mapping currently assumes `metal1`/`metal2` → [`M1`,`M3`]. If you change stack/layers, extend the small lookup in `placeNets()` accordingly.
- The LEF/DEF parsers remain intentionally minimal; they accept the constructs in the provided ViPeR examples. Unusual constructs may need small parser extensions.

---

## Contact

If you hit any issues reproducing the build or the flow, feel free to open an issue on your fork or include notes in the PR so reviewers can help iterate.
17 changes: 17 additions & 0 deletions include/chipsmith/chipFill.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ class chipSmith{
map<string, string> gdsFileLoc;
map<string, string> lef2gdsNames;
map<string, string> gdsFillFileLoc;

// NEW: layer translation and GDS mapping
map<string, string> layerLookup; // DEF layer -> canonical metal (e.g. "metal1" -> "M1")
map<string, int> metalLayerGds; // canonical metal -> GDS layer number (e.g. "M1" -> 10)'

// NEW: via strategy
// from canonical metal layer -> (to canonical layer -> GDS via cell name)
map<string, map<string, string>> viaStrategy;

// map<string, vector<int>> cellSize;
vector<vector<vector<bool>>> grid;
Expand All @@ -49,6 +57,8 @@ class chipSmith{
bool fillEnable = true;
unsigned int gateHeight = 0;
float PTLwidth = 0;
float mainBiasLineWidth = 0; // NEW: width of main bias grid lines
float biasBranchWidth = 0; // NEW: width of bias branches to gates
vector<int> fillCor;
unsigned int gridSize = 0;
map<string, int> GateBiasCorX;
Expand All @@ -65,6 +75,13 @@ class chipSmith{
int placeNets();
int placeFill();
int placeBias();

double cfgUnits = 1e-6; // e.g., microns from config
double gdsUnits = 1e-9; // gdsForge writes in 1e-9 meters
double U = 1000.0; // scale = cfgUnits / gdsUnits (default 1e-6 / 1e-9)

// helper to convert “config units” → integer GDS database units
inline int toGDSi(double v) const { return (int)std::lround(v * U); }

public:
chipSmith(){};
Expand Down
1 change: 1 addition & 0 deletions include/gdscpp/gdsParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define gdsParser

#include <bitset>
#include <cstdint>
#include <cstring>
#include <fstream>
#include <iostream>
Expand Down
27 changes: 19 additions & 8 deletions src/chipsmith/ParserLef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ int lef_file::importFile(const string &fileName){

while(1){
lineVec = splitFileLine(lefFile);
if(lineVec.size() == 0){ // ignore blank lines
continue;
}
keyword = lineVec[0];
if(blkEndWithName.find(keyword) != blkEndWithName.end()){

Expand Down Expand Up @@ -87,20 +90,28 @@ int lef_file::importFile(const string &fileName){
cout << "Found an alone END, miss match..." << endl;
}

}
else if(keyword == "VERSION" ||
keyword == "BUSBITCHARS" ||
keyword == "DIVIDERCHAR" ||
keyword == "MANUFACTURINGGRID" ||
keyword == "CLEARANCEMEASURE" ||
keyword == "USEMINSPACING" ||
keyword == "SITE" ||
keyword == "UNITS")
{
// LEF 5.x header / global configuration keywords that chipSmith does not use.
// We simply skip these lines (any nested blocks are consumed above).
continue;
}
else {
// word not in the library, out error;

cout << "Error with line ->" << endl;
// Unknown top-level keyword: warn and skip (for forward compatibility)
cout << "Warning: unknown LEF keyword, skipping line ->" << endl;
disVector(lineVec);
cout << "<--------------------" << endl;

cout << "String not found in lef dictionary" << endl;
cout << "Totsiens!" << endl;
return 0;
continue;
}


}
lefFile.close();
return 0;
Expand Down
Loading