template files and paths

This commit is contained in:
matt venn
2023-03-16 15:41:54 +01:00
parent 9e6891f111
commit b5745ccf4d
9 changed files with 8581 additions and 24 deletions
+5 -3
View File
@@ -1,5 +1,6 @@
import logging import logging
import json import json
import os
class CaravelConfig(): class CaravelConfig():
@@ -7,6 +8,7 @@ class CaravelConfig():
def __init__(self, projects, num_projects): def __init__(self, projects, num_projects):
self.projects = projects self.projects = projects
self.num_projects = num_projects self.num_projects = num_projects
self.script_dir = os.path.dirname(os.path.realpath(__file__))
# create macro file & positions, power hooks # create macro file & positions, power hooks
def create_macro_config(self): def create_macro_config(self):
@@ -87,7 +89,7 @@ class CaravelConfig():
logging.info(f"total user macros placed: {num_macros_placed}") logging.info(f"total user macros placed: {num_macros_placed}")
with open("upw_config.json") as fh: with open(os.path.join(self.script_dir, 'caravel_template', 'upw_config.json')) as fh:
caravel_config = json.load(fh) caravel_config = json.load(fh)
power_domains = "vccd1 vssd1 vccd1 vssd1" power_domains = "vccd1 vssd1 vccd1 vssd1"
@@ -215,12 +217,12 @@ class CaravelConfig():
# Write to file # Write to file
with open('verilog/rtl/user_project_wrapper.v', 'w') as fh: with open('verilog/rtl/user_project_wrapper.v', 'w') as fh:
# Insert the Caravel preamble # Insert the Caravel preamble
with open("upw_pre.v", "r") as fh_pre: with open(os.path.join(self.script_dir, 'caravel_template', 'upw_pre.v')) as fh_pre:
fh.write(fh_pre.read()) fh.write(fh_pre.read())
# Indent, join, and insert the module instances # Indent, join, and insert the module instances
fh.write("\n".join([(" " + x).rstrip() for x in body])) fh.write("\n".join([(" " + x).rstrip() for x in body]))
# Insert the Caravel postamble # Insert the Caravel postamble
with open("upw_post.v", "r") as fh_post: with open(os.path.join(self.script_dir, 'caravel_template', 'upw_post.v')) as fh_post:
fh.write(fh_post.read()) fh.write(fh_post.read())
# build the blackbox_project_includes.v file - used for blackboxing when building the GDS # build the blackbox_project_includes.v file - used for blackboxing when building the GDS
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
RBA::Application.instance.main_window.current_view.save_image("./tinytapeout.png",2000,2000)
+247
View File
@@ -0,0 +1,247 @@
<?xml version="1.0" encoding="utf-8"?>
<config>
<absolute-units>false</absolute-units>
<abstract-mode-enabled>false</abstract-mode-enabled>
<abstract-mode-width>10.0</abstract-mode-width>
<apply-text-trans>true</apply-text-trans>
<background-color>auto</background-color>
<bitmap-caching>true</bitmap-caching>
<bitmap-oversampling>1</bitmap-oversampling>
<cell-list-sorting>by-name</cell-list-sorting>
<child-context-color>auto</child-context-color>
<child-context-dimming>50</child-context-dimming>
<child-context-enabled>false</child-context-enabled>
<child-context-hollow>false</child-context-hollow>
<cib-context-cell/>
<cib-context-mode>any-top</cib-context-mode>
<cib-max-inst-count>1000</cib-max-inst-count>
<cib-window-dim>1.0</cib-window-dim>
<cib-window-mode>fit-marker</cib-window-mode>
<cib-window-state/>
<circle-points>32</circle-points>
<clear-ruler-new-cell>false</clear-ruler-new-cell>
<color-palette/>
<combine-mode>add</combine-mode>
<context-color>auto</context-color>
<context-dimming>50</context-dimming>
<context-hollow>false</context-hollow>
<current-lib-view/>
<current-ruler-template>0</current-ruler-template>
<custom-macro-paths/>
<dbu-units>false</dbu-units>
<def-import-spec/>
<default-add-other-layers>false</default-add-other-layers>
<default-font-size>0</default-font-size>
<default-grids>0.01,0.005,0.001</default-grids>
<default-layer-properties/>
<default-text-size>0.1</default-text-size>
<diff-detailed>false</diff-detailed>
<diff-exact>false</diff-exact>
<diff-expand-cell-arrays>false</diff-expand-cell-arrays>
<diff-run-xor>false</diff-run-xor>
<diff-summarize>false</diff-summarize>
<digits-dbu>2</digits-dbu>
<digits-micron>5</digits-micron>
<draw-array-border-instances>false</draw-array-border-instances>
<drawing-workers>1</drawing-workers>
<drop-small-cells>false</drop-small-cells>
<drop-small-cells-condition>0</drop-small-cells-condition>
<drop-small-cells-value>10</drop-small-cells-value>
<edit-connect-angle-mode>any</edit-connect-angle-mode>
<edit-grid>global</edit-grid>
<edit-hier-copy-mode>-1</edit-hier-copy-mode>
<edit-inst-angle>0</edit-inst-angle>
<edit-inst-array>false</edit-inst-array>
<edit-inst-cell-name/>
<edit-inst-column_x>0</edit-inst-column_x>
<edit-inst-column_y>0</edit-inst-column_y>
<edit-inst-columns>1</edit-inst-columns>
<edit-inst-lib-name/>
<edit-inst-mirror>false</edit-inst-mirror>
<edit-inst-pcell-parameters/>
<edit-inst-place-origin>false</edit-inst-place-origin>
<edit-inst-row_x>0</edit-inst-row_x>
<edit-inst-row_y>0</edit-inst-row_y>
<edit-inst-rows>1</edit-inst-rows>
<edit-inst-scale>1</edit-inst-scale>
<edit-max-shapes-of-instances>1000</edit-max-shapes-of-instances>
<edit-mode>false</edit-mode>
<edit-move-angle-mode>any</edit-move-angle-mode>
<edit-path-ext-type>flush</edit-path-ext-type>
<edit-path-ext-var-begin>0.0</edit-path-ext-var-begin>
<edit-path-ext-var-end>0.0</edit-path-ext-var-end>
<edit-path-width>0.1</edit-path-width>
<edit-show-shapes-of-instances>true</edit-show-shapes-of-instances>
<edit-snap-to-objects>false</edit-snap-to-objects>
<edit-text-halign>left</edit-text-halign>
<edit-text-size>0</edit-text-size>
<edit-text-string>ABC</edit-text-string>
<edit-text-valign>bottom</edit-text-valign>
<edit-top-level-selection>false</edit-top-level-selection>
<fit-new-cell>true</fit-new-cell>
<flat-cell-list>false</flat-cell-list>
<full-hierarchy-new-cell>true</full-hierarchy-new-cell>
<global-trans>r0</global-trans>
<grid-axis-color>auto</grid-axis-color>
<grid-color>auto</grid-color>
<grid-grid-color>auto</grid-grid-color>
<grid-micron>0.001</grid-micron>
<grid-ruler-color>auto</grid-ruler-color>
<grid-show-ruler>true</grid-show-ruler>
<grid-style0>invisible</grid-style0>
<grid-style1>dots</grid-style1>
<grid-style2>tenths-dotted-lines</grid-style2>
<grid-visible>true</grid-visible>
<guiding-shape-color>auto</guiding-shape-color>
<guiding-shape-line-width>1</guiding-shape-line-width>
<guiding-shape-vertex-size>5</guiding-shape-vertex-size>
<guiding-shape-visible>true</guiding-shape-visible>
<hide-empty-layers>false</hide-empty-layers>
<image-cache-size>1</image-cache-size>
<initial-hier-depth>1</initial-hier-depth>
<initial-technology/>
<inst-color>auto</inst-color>
<inst-label-font>0</inst-label-font>
<inst-label-transform>true</inst-label-transform>
<inst-visible>true</inst-visible>
<key-bindings/>
<l2ndb-export-circuit-cell-prefix>CIRCUIT_</l2ndb-export-circuit-cell-prefix>
<l2ndb-export-device-cell-prefix>DEVICE_</l2ndb-export-device-cell-prefix>
<l2ndb-export-net-cell-prefix>NET_</l2ndb-export-net-cell-prefix>
<l2ndb-export-net-propname/>
<l2ndb-export-produce-circuit-cells>false</l2ndb-export-produce-circuit-cells>
<l2ndb-export-produce-device-cells>false</l2ndb-export-produce-device-cells>
<l2ndb-export-start-layer-number>1000</l2ndb-export-start-layer-number>
<l2ndb-marker-color>auto</l2ndb-marker-color>
<l2ndb-marker-cycle-colors>255,0,0 0,255,0 0,0,255 255,255,0 255,0,255 0,255,255 160,80,255 255,160,0</l2ndb-marker-cycle-colors>
<l2ndb-marker-cycle-colors-enabled>false</l2ndb-marker-cycle-colors-enabled>
<l2ndb-marker-dither-pattern>-1</l2ndb-marker-dither-pattern>
<l2ndb-marker-halo>-1</l2ndb-marker-halo>
<l2ndb-marker-intensity>50</l2ndb-marker-intensity>
<l2ndb-marker-line-width>-1</l2ndb-marker-line-width>
<l2ndb-marker-use-original-colors>false</l2ndb-marker-use-original-colors>
<l2ndb-marker-vertex-size>-1</l2ndb-marker-vertex-size>
<l2ndb-max-shapes-highlighted>10000</l2ndb-max-shapes-highlighted>
<l2ndb-show-all>true</l2ndb-show-all>
<l2ndb-window-dim>1.0</l2ndb-window-dim>
<l2ndb-window-mode>fit-net</l2ndb-window-mode>
<l2ndb-window-state/>
<layers-always-show-layout-index>false</layers-always-show-layout-index>
<layers-always-show-ld>true</layers-always-show-ld>
<layers-always-show-source>false</layers-always-show-source>
<layout-file-watcher-enabled>true</layout-file-watcher-enabled>
<lef-import-spec/>
<line-style-palette/>
<macro-editor-active-macro/>
<macro-editor-console-interpreter/>
<macro-editor-console-mru/>
<macro-editor-current-macro/>
<macro-editor-debugging-enabled>true</macro-editor-debugging-enabled>
<macro-editor-file-watcher-enabled>true</macro-editor-file-watcher-enabled>
<macro-editor-font-family/>
<macro-editor-font-size/>
<macro-editor-indent>2</macro-editor-indent>
<macro-editor-open-macros/>
<macro-editor-save-all-on-run>false</macro-editor-save-all-on-run>
<macro-editor-stop-on-exception>true</macro-editor-stop-on-exception>
<macro-editor-styles/>
<macro-editor-tab-width>8</macro-editor-tab-width>
<macro-editor-watch-expressions/>
<macro-editor-window-state/>
<markers-visible>true</markers-visible>
<menu-items-hidden/>
<min-inst-label-size>16</min-inst-label-size>
<mouse-wheel-mode>0</mouse-wheel-mode>
<mru>'/home/matt/work/asic-workshop/shuttle6/zero_to_asic_mpw6/gds/user_project_wrapper.gds.gz' '/home/matt/work/asic-workshop/shuttle7/zero_to_asic_mpw7/gds/user_project_wrapper.gds.gz' '/home/matt/work/asic-workshop/shuttle7/tinytapeout-02/gds/user_project_wrapper.gds' '/home/matt/work/asic-workshop/shuttle8/tinytapeout-02/gds/user_project_wrapper.gds' '/home/matt/work/asic-workshop/shuttle9/caravel_user_project/gds/user_project_wrapper.gds'</mru>
<navigator-show-all-hier-levels>false</navigator-show-all-hier-levels>
<navigator-show-images>true</navigator-show-images>
<no-stipple>false</no-stipple>
<nt-marker-color>auto</nt-marker-color>
<nt-marker-cycle-colors>255,0,0 0,255,0 0,0,255 255,255,0 255,0,255 0,255,255 160,80,255 255,160,0</nt-marker-cycle-colors>
<nt-marker-cycle-colors-enabled>false</nt-marker-cycle-colors-enabled>
<nt-marker-dither-pattern>-1</nt-marker-dither-pattern>
<nt-marker-halo>-1</nt-marker-halo>
<nt-marker-intensity>50</nt-marker-intensity>
<nt-marker-line-width>-1</nt-marker-line-width>
<nt-marker-vertex-size>-1</nt-marker-vertex-size>
<nt-max-shapes-highlighted>10000</nt-max-shapes-highlighted>
<nt-window-dim>1.0</nt-window-dim>
<nt-window-mode>fit-net</nt-window-mode>
<pan-distance>0.15</pan-distance>
<paste-display-mode>2</paste-display-mode>
<pcb-import-spec/>
<rdb-context-mode>database-top</rdb-context-mode>
<rdb-marker-color>auto</rdb-marker-color>
<rdb-marker-dither-pattern>-1</rdb-marker-dither-pattern>
<rdb-marker-halo>-1</rdb-marker-halo>
<rdb-marker-line-width>-1</rdb-marker-line-width>
<rdb-marker-vertex-size>-1</rdb-marker-vertex-size>
<rdb-max-marker-count>1000</rdb-max-marker-count>
<rdb-window-dim>1.0</rdb-window-dim>
<rdb-window-mode>fit-marker</rdb-window-mode>
<rdb-window-state-v2/>
<reader-options-show-always>false</reader-options-show-always>
<ruler-color>auto</ruler-color>
<ruler-grid-snap>false</ruler-grid-snap>
<ruler-halo>true</ruler-halo>
<ruler-obj-snap>true</ruler-obj-snap>
<ruler-snap-mode>any</ruler-snap-mode>
<ruler-snap-range>8</ruler-snap-range>
<ruler-templates>mode=normal,title=Ruler,category=_ruler,fmt=$D,fmt_x=$X,fmt_y=$Y,position=auto,xalign=auto,yalign=auto,xlabel_xalign=auto,xlabel_yalign=auto,ylabel_xalign=auto,ylabel_yalign=auto,style=ruler,outline=diag,snap=true,angle_constraint=global;mode=single_click,title=Cross,category=_cross,fmt='$U,$V',fmt_x='',fmt_y='',position=auto,xalign=auto,yalign=auto,xlabel_xalign=auto,xlabel_yalign=auto,ylabel_xalign=auto,ylabel_yalign=auto,style=cross_both,outline=diag,snap=true,angle_constraint=global;mode=auto_metric,title=Measure,category=_measure,fmt=$D,fmt_x=$X,fmt_y=$Y,position=auto,xalign=auto,yalign=auto,xlabel_xalign=auto,xlabel_yalign=auto,ylabel_xalign=auto,ylabel_yalign=auto,style=ruler,outline=diag,snap=true,angle_constraint=global;mode=normal,title=Ellipse,category='',fmt='',fmt_x='W=$(abs(X))',fmt_y='H=$(abs(Y))',position=auto,xalign=auto,yalign=auto,xlabel_xalign=auto,xlabel_yalign=auto,ylabel_xalign=auto,ylabel_yalign=auto,style=line,outline=ellipse,snap=true,angle_constraint=global;mode=normal,title=Box,category='',fmt='',fmt_x='W=$(abs(X))',fmt_y='H=$(abs(Y))',position=auto,xalign=auto,yalign=auto,xlabel_xalign=auto,xlabel_yalign=auto,ylabel_xalign=auto,ylabel_yalign=auto,style=line,outline=box,snap=true,angle_constraint=global;mode=normal,title=XSection,category=XS,fmt=XS,fmt_x='',fmt_y='',position=auto,xalign=auto,yalign=auto,xlabel_xalign=auto,xlabel_yalign=auto,ylabel_xalign=auto,ylabel_yalign=auto,style=arrow_both,outline=diag,snap=true,angle_constraint=global</ruler-templates>
<rulers>-1</rulers>
<salt-manager-window-state/>
<search-range>5</search-range>
<sel-color>auto</sel-color>
<sel-dither-pattern>1</sel-dither-pattern>
<sel-halo>true</sel-halo>
<sel-inside-pcells-mode>false</sel-inside-pcells-mode>
<sel-line-width>1</sel-line-width>
<sel-transient-mode>true</sel-transient-mode>
<sel-vertex-size>3</sel-vertex-size>
<shb-context-cell/>
<shb-context-mode>any-top</shb-context-mode>
<shb-max-inst-count>1000</shb-max-inst-count>
<shb-max-shape-count>1000</shb-max-shape-count>
<shb-window-dim>1.0</shb-window-dim>
<shb-window-mode>fit-marker</shb-window-mode>
<shb-window-state/>
<show-bookmarks-view>false</show-bookmarks-view>
<show-hierarchy-panel>true</show-hierarchy-panel>
<show-layer-panel>true</show-layer-panel>
<show-layer-toolbox>true</show-layer-toolbox>
<show-libraries-view>true</show-libraries-view>
<show-navigator>false</show-navigator>
<show-properties>false</show-properties>
<show-toolbar>true</show-toolbar>
<split-cell-list>false</split-cell-list>
<split-lib-views>false</split-lib-views>
<sr-max-item-count>1000</sr-max-item-count>
<sr-window-dim>1.0</sr-window-dim>
<sr-window-mode>fit-marker</sr-window-mode>
<sr-window-state/>
<stipple-offset>true</stipple-offset>
<stipple-palette/>
<stream-import-spec2/>
<synchronized-views>false</synchronized-views>
<tech-editor-window-state/>
<technology-data/>
<test-shapes-in-view>false</test-shapes-in-view>
<text-color>auto</text-color>
<text-font>0</text-font>
<text-lazy-rendering>true</text-lazy-rendering>
<text-visible>true</text-visible>
<tip-window-hidden>editor-mode=4,editor-mode=0</tip-window-hidden>
<window-geometry/>
<window-state/>
<xor-anotb>false</xor-anotb>
<xor-axorb>true</xor-axorb>
<xor-bnota>false</xor-bnota>
<xor-input-mode>all</xor-input-mode>
<xor-layer-offset/>
<xor-num-workers>1</xor-num-workers>
<xor-output-mode>rdb</xor-output-mode>
<xor-region-mode>all</xor-region-mode>
<xor-summarize>false</xor-summarize>
<xor-tiling/>
<xor-tolerances/>
</config>
+4
View File
@@ -0,0 +1,4 @@
// end of module instantiation
endmodule // user_project_wrapper
`default_nettype wire
+84
View File
@@ -0,0 +1,84 @@
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
/*
*-------------------------------------------------------------
*
* user_project_wrapper
*
* This wrapper enumerates all of the pins available to the
* user for the user project.
*
* An example user project is provided in this wrapper. The
* example should be removed and replaced with the actual
* user project.
*
* THIS FILE HAS BEEN GENERATED USING multi_tools_project CODEGEN
* IF YOU NEED TO MAKE EDITS TO IT, EDIT codegen/caravel_iface_header.txt
*
*-------------------------------------------------------------
*/
module user_project_wrapper #(
parameter BITS = 32
)(
`ifdef USE_POWER_PINS
inout vdda1, // User area 1 3.3V supply
inout vdda2, // User area 2 3.3V supply
inout vssa1, // User area 1 analog ground
inout vssa2, // User area 2 analog ground
inout vccd1, // User area 1 1.8V supply
inout vccd2, // User area 2 1.8v supply
inout vssd1, // User area 1 digital ground
inout vssd2, // User area 2 digital ground
`endif
// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,
// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oenb,
// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb,
// Analog (direct connection to GPIO pad---use with caution)
// Note that analog I/O is not available on the 7 lowest-numbered
// GPIO pads, and so the analog_io indexing is offset from the
// GPIO indexing by 7 (also upper 2 GPIOs do not have analog_io).
inout [`MPRJ_IO_PADS-10:0] analog_io,
// Independent clock (on independent integer divider)
input user_clock2,
// User maskable interrupt signals
output [2:0] user_irq
);
// start of module instantiation
-10
View File
@@ -13,16 +13,6 @@ from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE, SIG_DFL) signal(SIGPIPE, SIG_DFL)
"""
# if the project is a filler, then use the config from the first fill project
def gen_local_dir(self, fill_id):
if self.fill:
return os.path.join(os.path.join(self.project_dir, f'{fill_id :03}'))
else:
return os.path.join(os.path.join(self.project_dir, f'{self.index :03}'))
"""
class Projects(): class Projects():
def __init__(self, config, args): def __init__(self, config, args):
+14 -11
View File
@@ -6,11 +6,12 @@ class Docs():
def __init__(self, projects, args): def __init__(self, projects, args):
self.projects = projects self.projects = projects
self.args = args self.args = args
self.script_dir = os.path.dirname(os.path.realpath(__file__))
# stuff related to docs # stuff related to docs
def build_index(self): def build_index(self):
logging.info("building doc index") logging.info("building doc index")
with open("README_init.md") as fh: with open(os.path.join(self.script_dir, 'docs', 'README_init.md')) as fh:
readme = fh.read() readme = fh.read()
with open("README.md", 'w') as fh: with open("README.md", 'w') as fh:
fh.write(readme) fh.write(readme)
@@ -21,7 +22,10 @@ class Docs():
fh.write(project.get_index_row()) fh.write(project.get_index_row())
def update_image(self): def update_image(self):
cmd = "klayout -l caravel.lyp gds/user_project_wrapper.gds -r dump_pic.rb -c klayoutrc" ruby = os.path.join(self.script_dir, 'caravel_template', 'dump_pic.rb')
klayoutrc = os.path.join(self.script_dir, 'caravel_template', 'klayoutrc')
lyp = os.path.join(self.script_dir, 'caravel_template', 'caravel.lyp')
cmd = f'klayout -l {lyp} gds/user_project_wrapper.gds -r {ruby} -c {klayoutrc}'
logging.info(cmd) logging.info(cmd)
os.system(cmd) os.system(cmd)
@@ -32,25 +36,24 @@ class Docs():
design = project.get_yaml() design = project.get_yaml()
designs.append(design) designs.append(design)
with open(self.args.dump_json, "w") as fh: with open(self.args.dump_json, 'w') as fh:
fh.write(json.dumps(designs, indent=4)) fh.write(json.dumps(designs, indent=4))
logging.info(f'wrote json to {self.args.dump_json}') logging.info(f'wrote json to {self.args.dump_json}')
def dump_markdown(self): def dump_markdown(self):
with open(os.path.join(self.script_dir, 'docs', 'doc_header.md')) as fh:
with open("doc_header.md") as fh:
doc_header = fh.read() doc_header = fh.read()
with open("doc_template.md") as fh: with open(os.path.join(self.script_dir, 'docs', 'doc_template.md')) as fh:
doc_template = fh.read() doc_template = fh.read()
with open("INFO.md") as fh: with open(os.path.join(self.script_dir, 'docs', 'INFO.md')) as fh:
doc_info = fh.read() doc_info = fh.read()
with open("VERIFICATION.md") as fh: with open(os.path.join(self.script_dir, 'docs', 'VERIFICATION.md')) as fh:
doc_verification = fh.read() doc_verification = fh.read()
with open("CREDITS.md") as fh: with open(os.path.join(self.script_dir, 'docs', 'CREDITS.md')) as fh:
doc_credits = fh.read() doc_credits = fh.read()
with open(self.args.dump_markdown, 'w') as fh: with open(self.args.dump_markdown, 'w') as fh:
@@ -104,10 +107,10 @@ class Docs():
os.makedirs(hugo_root) os.makedirs(hugo_root)
os.makedirs(hugo_images) os.makedirs(hugo_images)
with open("hugo_template.md") as fh: with open(os.path.join(self.script_dir, 'docs', 'hugo_template.md')) as fh:
doc_template = fh.read() doc_template = fh.read()
with open("hugo_index_template.md") as fh: with open(os.path.join(self.script_dir, 'docs', 'hugo_index_template.md')) as fh:
index_template = fh.read() index_template = fh.read()
# copy image # copy image